﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text;
using System.Linq;
using T.FAS.Runtime.Expression.Entity;
using T.FAS.Runtime.Base.Entity;
using T.FAS.WF.WorkFlow.Api;
using T.FAS.WF.WorkFlow.Model;
using T.FAS.Runtime.Expression.SPI;
using T.FAS.WF.Participant.SysPlugin;
using Newtonsoft.Json;
using Teld.Core.Error;

namespace T.FAS.Runtime.Expression.Plugin
{
    /// <summary>
    /// 审批流表达式执行插件
    /// </summary>
    [ExpressionPlugin(methods: "Submit,Revoke,GetState,CanApproval,Approval,GetUsers,GetUsersByRoles,GetDepartmentHeadsByUser,GetMultiLevelSupervisorsByUser")]
    public class AFExecutor : DynamicObject, IDynamicActionAdapter
    {
        public readonly static string ParticipantStr = "Participant";
        private readonly FasWFClient _client = new FasWFClient();
        private readonly ParticipantObject _participantObject = new ParticipantObject();

        /// <summary>
        /// JS脚本动态调用Dynamic必备函数
        /// 脚本写法：WF.DQ_GetUser();
        /// </summary>
        /// <param name="name">动态调用DynamicObject中的函数名称</param>
        /// <param name="args">参数信息，参数类型必须增加 params</param>
        /// <returns></returns>
        public object DynamicInvoke(string name, params object[] args)
        {
            return ExcuteAF(name, args);
        }

        private object DynamicGetMember(string name)
        {
            if (string.Equals(name, ParticipantStr))
            {
                return _participantObject;
            }
            else
            {
                throw new TeldException("FASWF-AFExecutor-Participant-0001", $"不支持的AF对象属性:{name}");
            }
        }

        private object ExcuteAF(string actionID, object[] paramList)
        {
            SysUserManagerClient sysUserManagerClient;
            if (actionID == "Submit")
            {
                SubmitParam submit = new SubmitParam();
                submit.ProcessDefinitionKey = Convert.ToString(paramList[0]);
                submit.Variables = JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonConvert.SerializeObject(paramList[1]));
                submit.ProcessInstanceName = Convert.ToString(paramList[2]);
                submit.BusinessKey = Convert.ToString(paramList[3]);
                submit.StartUserId = Convert.ToString(paramList[4]);
                return _client.Submit(submit);
            }
            else if (actionID == "Revoke")
            {
                string processDefinitionKey = Convert.ToString(paramList[0]);
                string businessKey = Convert.ToString(paramList[1]);
                _client.Revoke(processDefinitionKey, businessKey);
                return "";
            }
            else if (actionID == "GetState")
            {
                string processDefinitionKey = Convert.ToString(paramList[0]);
                string businessKey = Convert.ToString(paramList[1]);
                return _client.GetState(processDefinitionKey, businessKey);
            }
            else if (actionID == "GetUsers")
            {
                sysUserManagerClient = new SysUserManagerClient();
                List<string> userIds = new List<string>();
                foreach (var item in paramList)
                {
                    userIds.Add(Convert.ToString(item));
                }
                return sysUserManagerClient.GetUsers(userIds);
            }
            else if (actionID == "GetUsersByRoles")
            {
                sysUserManagerClient = new SysUserManagerClient();
                List<string> roleIds = new List<string>();
                foreach (var item in paramList)
                {
                    roleIds.Add(Convert.ToString(item));
                }
                return sysUserManagerClient.GetUsersByRoles(roleIds);
            }
            else if (actionID == "GetDepartmentHeadsByUser")
            {
                sysUserManagerClient = new SysUserManagerClient();
                string userId = Convert.ToString(paramList[0]);
                return sysUserManagerClient.GetDepartmentHeadsByUser(userId);
            }
            else if (actionID == "GetMultiLevelSupervisorsByUser")
            {
                sysUserManagerClient = new SysUserManagerClient();
                string userId = Convert.ToString(paramList[0]);
                int level = Convert.ToInt32(paramList[1].ToString());
                return sysUserManagerClient.GetMultiLevelSupervisorsByUser(userId, level);
            }
            else
            {
                throw new TeldException("WF-AFExecutor-0001", "不支持的AF方法:" + actionID);
            }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = DynamicGetMember(binder.Name);
            return true;
        }
    }
}
